#ifndef GENERIC_GRAPH_BUILDER
#define GENERIC_GRAPH_BUILDER

#include <string>

#include <boost/graph/properties.hpp>
#include <boost/graph/adjacency_list.hpp>

#include "GraphTypes.h"

namespace Graphs {

	template <typename T = std::string>
	class GenericGraphBuilder {
		public:
			//edge connecting word property
			typedef boost::property<boost::edge_connecting_word_t,T> edge_connecting_word_prop_t;
			typedef boost::adjacency_list<boost::listS,
																	boost::vecS,
																	boost::directedS,
																	boost::property<boost::vertex_index_t, long, 
																	 vertex_frequency_prop_t> , //vertex property map
																	boost::property<boost::edge_section_type_t,Dictionary::SectionType,
																	 edge_connecting_word_prop_t > , //edge property map
																	graph_source_prop_t > graph_t;

			GenericGraphBuilder() : document(NULL) {}
			GenericGraphBuilder(Dictionary::Document<T> *document) :document(document) {}

			void set_document(Dictionary::Document<T> *document) { this->document = document; }
			
			graph_t *build_graph();

		private:
			Dictionary::Document<T> *document;
			template < typename Edge >
				void set_edge_property( Edge &edge, Dictionary::Node<T> *node, Dictionary::Sentence<T> *sentence, Dictionary::SectionType section_type);

	};
}


template< typename T>
typename Graphs::GenericGraphBuilder<T >::graph_t * Graphs::GenericGraphBuilder<T>::build_graph()
{
	graph_t *graph = new graph_t;
	using  namespace Dictionary;


	/*property maps*/
	typedef boost::property_map<graph_t,boost::vertex_index_t         >::type vertex_index_map_t;
	typedef boost::property_map<graph_t,boost::vertex_frequency_t     >::type vertex_frequency_map_t;
	typedef boost::property_map<graph_t,boost::edge_section_type_t    >::type edge_section_type_map_t;
	typedef boost::property_map<graph_t,boost::edge_connecting_word_t >::type edge_connecting_word_map_t;
	typedef boost::property_map<graph_t,boost::graph_name_t           >::type graph_name_map_t;

	const Document<T>::id_to_node_t *id_to_node_map = document->get_node_array();
	Document<T>::id_to_node_t::const_iterator node_iter = id_to_node_map->begin(), node_end = id_to_node_map->end();

	const Node<T>::unique_sections_t * sections;
	Node<T>::unique_sections_t::const_iterator section_iter, section_end;
	const Section<T>::sentence_number_t *sentences;
	Section<T>::sentence_number_t::const_iterator sentence_iter,sentence_end;
	Section<T>::term_place_in_sentence_t::const_iterator place_i , place_end;

	Node<T> *node;
	Section<T> *section;
	Sentence<T> *sentence;
	long node_id , next_id;
	for (; node_iter != node_end; ++node_iter)
	{
    node = node_iter->second;
		node_id = node->get_id(); //get the id of the node
		//next iterate through all sections and sentences finding the next id of this term and connecting it through the edge

		sections = node->get_sections();
    section_iter = sections->begin(), section_end = sections->end();

		//iterate through sections
		for (;section_iter != section_end; ++section_iter)
		{

			  section = section_iter->second;
				sentences = section->get_sentence_array();

				sentence_iter = sentences->begin(); sentence_end = sentences->end();
				for (; sentence_iter != sentence_end; ++sentence_iter)
				{
					place_i = (sentence_iter->second)->begin(), place_end = (sentence_iter->second)->end();
					for (;  place_i != place_end; ++place_i)
					{
						sentence = place_i->second;
						next_id = sentence->get_next_id();

						if (next_id >= 0)
							std::cout << node_id << "-->" << next_id << std::endl;
						else
							std::cout << node_id << std::endl;

					}
				}
		}//end of for(;section_iter...
	}//end of for (; node_iter....

	return graph;
}
template <typename T>
  template < typename Edge >
   void Graphs::GenericGraphBuilder<T>::set_edge_property( Edge &edge, Dictionary::Node<T> *node, Dictionary::Sentence<T> *sentence, Dictionary::SectionType section_type)
{

}

#endif